package com.starsoft.quant.web;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.starsoft.frame.base.service.UserService;
import com.starsoft.frame.core.web.WebUtil;
import com.starsoft.frame.util.DateUtil;
import com.starsoft.frame.util.MapUtil;
import com.starsoft.frame.util.StringUtil;
import com.starsoft.quant.bean.QuantAcount;
import com.starsoft.quant.bean.QuantModel;
import com.starsoft.quant.executor.StrategyExecutor;
import com.starsoft.quant.executor.StrategyReport;
import com.starsoft.quant.service.QuantAcountService;
import com.starsoft.quant.service.QuantModelService;
import com.starsoft.quant.service.QuantReportService;
import com.starsoft.smdc.service.HolidayService;
import com.starsoft.trade.bean.TradeAcountStatus;
import com.starsoft.trade.bean.TradeBill;
import com.starsoft.trade.service.AcountStatusService;
import com.starsoft.trade.service.TradeBillService;

@RestController
@RequestMapping("/quant/report")
public class DetailReportController {

	@Autowired
	QuantAcountService acountService;

	@Autowired
	StrategyExecutor executor;

	@Autowired
	QuantReportService reportService;

	@Autowired
	HolidayService holidayService;

	@Autowired
	AcountStatusService acountStatusService;

	@Autowired
	TradeBillService billService;

	@Autowired
	QuantModelService modelService;

	@RequestMapping("/detailreportpage")
	public ModelAndView getAcountReportPage(HttpServletRequest request) throws Exception {
		ModelAndView mv = new ModelAndView("/quant/report/detailreport");
		Integer acountId = getAcountId(request);
		QuantModel quantModel = acountService.getModel(acountId);
		if (quantModel != null) {
			mv.addObject("model", modelService.getOrderedColumns(quantModel));
			if (!StringUtil.isEmpty(quantModel.getSortName()) && !StringUtil.isEmpty(quantModel.getSortOrder())) {
				mv.addObject("sortName", quantModel.getSortName());
				mv.addObject("sortOrder", quantModel.getSortOrder());
			} else {
				mv.addObject("sortName", "rating");
				mv.addObject("sortOrder", "desc");
			}
			mv.addObject("multiSort", quantModel.getMultiSort());

		} else {
			acountId = -1;
		}
		mv.addObject("acountId", acountId);
		return mv;
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/detailreport.json")
	public Map<String, Object> getAcountReport(HttpServletRequest request) throws Exception {
		Map<String, Object> model = new HashMap<>();
		Integer acountId = getAcountId(request);
		QuantModel quantModel = acountService.getModel(acountId);
		QuantAcount quantAcount = acountService.getAcount(acountId);
		if (quantAcount == null || quantAcount.getModelCode() == null) {
			model.put("sucesse", false);
			model.put("message", "未配置策略");
			return null;
		}

		String isForce = request.getParameter("isForce");
		Date summaryDate = getSummaryDate(request, quantAcount);
		if ("true".equalsIgnoreCase(isForce)) {
			executor.executor(acountId, summaryDate);
		}

		Map<String, Object> summary = new HashMap<String, Object>();
		List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();
		StrategyReport report = reportService.getReport(acountId, summaryDate);
		if (report != null && report.getSummary() != null) {
			Map<String, Object> reportMap = reportService.convertReport(report, quantModel);
			summary = (Map<String, Object>) reportMap.get("summary");
			details = (List<Map<String, Object>>) reportMap.get("details");
		}
		TradeAcountStatus status = acountStatusService.updateAndGet(acountId, summaryDate);
		MapUtil.copyMap(summary, MapUtil.toMap(status.getSummary()), false);
		summary.put("summaryDate", summaryDate);
		summary.put("acountId", acountId);
		List<TradeBill> billBean = billService.getBills(acountId, summaryDate, summaryDate);
		List<Map<String, Object>> bills = billService.convertToMap(billBean);

		model.put("summary", summary);
		model.put("details", details);
		model.put("bills", bills);
		return model;
	}

	private Integer getAcountId(HttpServletRequest request) {
		Integer acountId = null;
		String acountIdStr = request.getParameter("acountId");
		if (StringUtil.isEmpty(acountIdStr)) {
			acountId = UserService.getUserContext().getAcountId();
		} else {
			acountId = Integer.parseInt(acountIdStr);
		}
		return acountId;
	}

	private Date getSummaryDate(HttpServletRequest request, QuantAcount quantAcount) {
		Date summaryDate = WebUtil.getDate(request, "summaryDate", "yyyy-MM-dd");
		String summaryDateType = request.getParameter("summaryDateType");
		if (summaryDate == null) {
			summaryDate = new Date();
		}
		if ("lastDay".equalsIgnoreCase(summaryDateType)) {
			summaryDate = holidayService.getNextBusinessDay(summaryDate, -1);
		} else if ("nextDay".equalsIgnoreCase(summaryDateType)) {
			summaryDate = holidayService.getNextBusinessDay(summaryDate, 1);
		}
		if (summaryDate.after(new Date())) {
			summaryDate = new Date();
		}

		boolean isBusy = holidayService.isBusinessDay(summaryDate);
		if (DateUtil.isToday(summaryDate)) {
			boolean isBeforeOpen = holidayService.isBeforeOpen(new Date());
			if (!isBusy || isBeforeOpen) {
				summaryDate = holidayService.getNextBusinessDay(summaryDate, -1);
			}
		} else if (!isBusy) {
			summaryDate = holidayService.getNextBusinessDay(summaryDate, -1);
		}

		if (quantAcount.getEndDate() != null) {
			Date endDate = holidayService.getBusinessDay(quantAcount.getEndDate(), true);
			if (endDate.before(summaryDate)) {
				summaryDate = endDate;
			}
		}
		if (quantAcount.getStartDate() != null) {
			Date startDate = holidayService.getBusinessDay(quantAcount.getStartDate(), false);
			if (startDate.after(summaryDate)) {
				summaryDate = startDate;
			}
		}
		return summaryDate;
	}
}
